package com.beiding.jsonanalyzer.analyze.func.openfunc;

import com.beiding.jsonanalyzer.analyze.func.FuncBase;
import com.beiding.jsonanalyzer.analyze.func.FuncFactory;
import com.beiding.jsonanalyzer.analyze.func.base.*;

/**
 * @author 丁常磊
 * @date 2022/5/31 12:57
 */

public class FuncUtils {

    public static FuncFactory ensureFuncFactory(Object k) {
        if (k instanceof FuncFactory) {
            return (FuncFactory) k;
        }
        return LastGet.of(k);
    }


    /**
     * 构建多值函数
     * @param factory
     * @param keys
     * @param <W>
     * @return
     */
    public static <W extends FuncFactoryAdaptor<? extends MultiValueFunc>> W buildForMultiValue(W factory, Object... keys) {


        //工厂列表
        FuncFactory[] ffs = new FuncFactory[keys.length];

        //用key创建工厂列表
        for (int i = 0; i < keys.length; i++) {
            ffs[i] = FuncUtils.ensureFuncFactory(keys[i]);
        }

        //添加各种工厂
        factory.addForFunc(f -> {

            //用工厂创建函数
            FuncBase[] fs = new FuncBase[ffs.length];

            for (int i = 0; i < ffs.length; i++) {
                fs[i] = ffs[i].createInstance();
            }

            f.config(fs);
        });
        return factory;
    }


    /**
     * 创建一个简单函数
     * @param factory 函数工厂
     * @param core 内核函数
     * @param <W>
     * @return
     */
    public static <W extends FuncFactoryAdaptor<? extends EasyFunc>> W buildForEasyFunc(W factory, Object core) {
        FuncFactory fa = FuncUtils.ensureFuncFactory(core);
        factory.addForFunc(f -> {
            f.config(fa.createInstance());
        });

        return factory;
    }

    /**
     * 创建一个简单聚合函数
     * @param factory
     * @param exp
     * @param distinct
     * @param <W>
     * @return
     */
    public static <W extends FuncFactoryAdaptor<? extends EasyAggFunc>> W buildForEasyAgg(W factory, Object exp, boolean distinct) {
        Object z = FuncUtils.ensureFuncFactory(exp);
        factory.addForFunc(f -> {
            f.config(((FuncFactory) z).createInstance(), distinct);
        });
        return factory;
    }


}
